#include "logicwork.h"

#include <session.h>

LogicWork::LogicWork()
{
}

void LogicWork::start()
{
	workThread_ = std::make_shared<std::thread>([&]() {
		bStop_ = false;
		while (!bStop_) {
			std::shared_ptr<LogicNode> logicNode;
			{
				std::unique_lock<std::mutex> locker(logicLock_);
				while (logicQueue_.size() == 0 && !bStop_) {
					logicCond_.wait(locker);
				}
				if (bStop_)break;
				assert(logicQueue_.size() > 0);
				logicNode = logicQueue_.front();
				logicQueue_.pop();
			}
			handler(logicNode);
		}
		}
	);
}

void LogicWork::stop()
{
	bStop_ = true;
	{
		std::lock_guard<std::mutex> locker(logicLock_);
		while (logicQueue_.size() > 0) {
			auto logicNode = logicQueue_.front();
			logicQueue_.pop();
			handler(logicNode);
		}
	}
	logicCond_.notify_all();
	workThread_->join();
}

bool LogicWork::postTask(std::shared_ptr<LogicNode> logicNode)
{
	{
		std::lock_guard<std::mutex> locker(logicLock_);
		if (logicQueue_.size() > MAX_QUEUE_SIZE) {
			qDebug() << "logicQueue is fulled. size: " << logicQueue_.size();
			return false;
		}
		logicQueue_.push(logicNode);
	}
	logicCond_.notify_one();
	return true;
}

void LogicWork::handler(std::shared_ptr<LogicNode> logicNode)
{
	int msgId = logicNode->recvNode_->msgId_;
	auto recvNode = logicNode->recvNode_;
	if (msgId == static_cast<int>(MsgType::TYPE_TEXT)) {
		QString str = QString::asprintf("msgid:%1 dataLen:%2 data:%3\n").arg(recvNode->msgId_).arg(recvNode->totalLen_).arg(recvNode->data_);
		emit logicNode->session_->sigUpdateRecvData(str);
	}
	else if (msgId == static_cast<int>(MsgType::TYPE_FILE)) {
		// 读取header
		Json::CharReaderBuilder builder;
		const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
		Json::Value jsonObj;
		std::string err;
		if(!reader->parse(recvNode->data_, recvNode->data_ + recvNode->totalLen_, &jsonObj, &err)) {
			qDebug() << "parse to json: " << recvNode->data_;
			qDebug() << "parse str to json failed: " << QString().fromStdString(err);
			return;
		}
		// 获取body
		int type = jsonObj["type"].asInt();
		std::string data = jsonObj["data"].asString();
		//QString data = QString().fromStdString(jsonObj["data"].asString()); // 不能使用QString，否则会出现乱码，不知道为什么
		size_t size = jsonObj["dataLen"].asInt();
		std::string filename = jsonObj["filename"].asString();
		QString filePath = QString(FILE_PATH) + "/" + QString().fromStdString(filename);
		QFile file(filePath);
		file.open(QIODevice::Append);
		QDataStream out(&file);
		if (!file.isOpen()) {
			qDebug() << filePath << "open failed!";
			qDebug() << "open file error: "<< file.errorString();
			return;
		}
		if (type == static_cast<int>(FileType::TYPE_GET_FILE_TREE_RESPONSE)) {
			file.write(data.c_str(), size);
		}
		else if (type == static_cast<int>(FileType::TYPE_GET_FILE_TREE_FINISH)) {
			file.write(data.c_str(), size);
		}
		else if (type == static_cast<int>(FileType::TYPE_FILE_DOWNLOAD_RESPONSE)) {
			file.write(data.c_str(), size);
		}
		else if (type == static_cast<int>(FileType::TYPE_FILE_DOWNLOAD_RESPONSE_FINISH)) {
			file.write(data.c_str(), size);
		}
		file.close();
	}
	else {
		throw std::runtime_error("unknown msg type: " + std::to_string(msgId));
	}
}

LogicWork::~LogicWork()
{}
